#include <string.h>
#include "Queue.h"
#include "Common.h"
#ifdef LIST_QUEUE

struct Queue * CreateQueue(uint32_t itemNums, uint8_t itemSize)
{
    struct Queue * queue = NULL;
    struct QueueItem *qi = NULL;
    uint32_t maxSize     = (itemNums + 1)* itemSize;
    uint8_t valid_nums = 0;
    int i = 0;

    queue = MALLOC(sizeof(struct Queue) + maxSize);
    if (queue) {
        INIT_LIST_HEAD(&queue->busyNode.head);
        INIT_LIST_HEAD(&queue->idleNode.head);
        queue->busyNode.cnt = 0;
        queue->idleNode.cnt = 0;

        for (i = 0; i < itemNums; i++) {
            qi = MALLOC(sizeof(struct QueueItem) + itemSize);

            if (!qi) {
                break;
            }

            valid_nums++;
            qi->item = (char*)qi + sizeof(struct QueueItem);
            list_add_tail(&qi->entry, &queue->idleNode.head);
            queue->idleNode.cnt++;
        }
        queue->itemNums = valid_nums;
        queue->itemSize = itemSize;
        printf("Queue:%08X  itemNums:%X itemSize:%d\n", (uint32_t)queue, queue->itemNums, queue->itemSize);
    }

    return queue;
}

void ReleaseQueue(struct Queue* queue)
{
    struct QueueItem *qi = NULL, *tmp = NULL;
    list_for_each_entry_safe(qi, tmp, &queue->busyNode.head, entry) {
        dprint("free busyNode");
        FREE(qi);
    }
    list_for_each_entry_safe(qi, tmp, &queue->idleNode.head, entry) {
        dprint("free idleNode");
        FREE(qi);
    }
    FREE(queue);
}

bool FullQueue(struct Queue * queue)
{
    return false;
}

bool EmptyQueue(struct Queue * queue)
{
    return list_empty_careful(&queue->busyNode.head);
}

bool PushQueue(struct Queue * queue, void* item)
{
    struct QueueItem *qi = NULL;
    qi = list_first_entry(queue->idleNode.head.next, struct QueueItem, entry);
    list_del_init(&qi->entry);
    queue->idleNode.cnt--;

    return true;
}

bool PopQueue(struct Queue * queue, void* item)
{
    return true;
}
#else
struct Queue * CreateQueue(uint32_t itemNums, uint8_t itemSize)
{
    struct Queue * queue = NULL;
    uint32_t maxSize     = (itemNums + 1)* itemSize;
    queue = MALLOC(sizeof(struct Queue) + maxSize);
    if (queue) {
        queue->pBase   = (uint8_t*)queue + sizeof(struct Queue);
        queue->front   = 0;
        queue->rear    = 0;
        queue->maxSize = maxSize;
        queue->itemSize = itemSize;
        printf("Queue:%08X pBase:%08X QueueSize:%X maxSize:%d itemSize:%d\n", (uint32_t)queue, (uint32_t)queue->pBase, sizeof(struct Queue), queue->maxSize, queue->itemSize);
    }

    return queue;
}

void ReleaseQueue(struct Queue* queue)
{
    FREE(queue);
}

bool FullQueue(struct Queue * queue)
{
    if(queue->front==(queue->rear + queue->itemSize) % queue->maxSize)  {  //判断循环链表是否满，留一个预留空间不用
        return true;
    } else {
        return false;
    }
}
bool EmptyQueue(struct Queue * queue)
{
    if(queue->front == queue->rear) {   //判断是否为空
        return true;
    } else {
        return false;
    }
}
bool PushQueue(struct Queue * queue, void* item)
{
    if(FullQueue(queue)) {
        return false;
    } else {
        memcpy((uint8_t*)queue->pBase + queue->rear, item, queue->itemSize);
        queue->rear = (queue->rear + queue->itemSize) % queue->maxSize;
        return true;
    }
}

bool PopQueue(struct Queue * queue, void* item)
{
    if(EmptyQueue(queue)) {
        return false;
    } else {
        memcpy(item, (uint8_t*)queue->pBase+queue->front, queue->itemSize);
        queue->front = (queue->front + queue->itemSize) % queue->maxSize;
        return true;
    }
}
#endif
